use std::collections::HashMap;

use super::Graph;

type ST = HashMap<String, usize>;
pub struct SymbolGraph {
    /// 符号名 --> 索引
    st: ST,
    ///  索引 -->  符号名
    keys: Vec<String>,
    /// 图
    _g: Graph,
}
impl SymbolGraph {
    pub fn new(stream: &str, sp: &str) -> Self {
        let mut st = ST::new();
        let lines = stream.lines();
        for line in lines {
            let a: Vec<&str> = line.trim().split(sp).filter(|it| !it.is_empty()).collect();
            for key in a {
                if !st.contains_key(key) {
                    st.insert(key.to_string(), st.len());
                }
            }
        }
        let mut keys = vec!["".to_string(); st.len()];
        for (key, value) in st.iter() {
            keys[*value] = key.clone();
        }
        let mut g = Graph::new(keys.len());
        let lines = stream.lines();
        for line in lines {
            let a: Vec<&str> = line.trim().split(sp).filter(|it| !it.is_empty()).collect();
            if !a.is_empty() {
                let v = *st.get(a[0]).unwrap();
                for w in a.into_iter().skip(1) {
                    g.add_edge(v, *st.get(w).unwrap());
                }
            }
        }
        SymbolGraph { st, keys, _g: g }
    }
    /// key是一个顶点吗
    pub fn contains(&self, key: &str) -> bool {
        self.st.contains_key(key)
    }
    /// key的索引
    pub fn index(&self, key: &str) -> usize {
        *self.st.get(key).unwrap()
    }
    /// 索引v的顶点名
    pub fn name(&self, v: usize) -> &str {
        &self.keys[v]
    }
}
#[cfg(test)]
mod test {
    use super::SymbolGraph;

    #[test]
    fn test() {
        let sg = SymbolGraph::new(
            r#"
      a b
      c d
      e f
      a d
      "#,
            " ",
        );
        assert_eq!(sg.contains("a"), true);
        assert_eq!(sg.contains("f"), true);
        assert_eq!(sg.contains("aa"), false);
        assert_eq!(sg.index("a"), 0);
        assert_eq!(sg.index("b"), 1);
        assert_eq!(sg.index("c"), 2);
        assert_eq!(sg.index("d"), 3);
        assert_eq!(sg.index("e"), 4);
        assert_eq!(sg.index("f"), 5);
        assert_eq!(sg.name(0), "a");
        assert_eq!(sg.name(5), "f");
    }
}
